home *** CD-ROM | disk | FTP | other *** search
/ BBS Toolkit / BBS Toolkit.iso / doors_2 / o_ren171.zip / O_RENUM.C next >
Text File  |  1991-08-05  |  41KB  |  1,455 lines

  1. /* #define OS2  1 */
  2. /**************************************************************************
  3.  I hate to do this, but here goes:
  4.  
  5. The source code for O_RENUM is provided for your use and examination.
  6.  
  7. Because of a recent malicious "hack" of the source code, you are ASKED NOT
  8. to make the source available for DownLoad or FileRequest without my
  9. permission.  This is to protect the FIDOnet community more than it is
  10. to protect the source code itself.
  11.  
  12. If you make any changes to the program that you would like to see
  13. incorporated into MY next release, please SEND CODE <tm, Wynn Wagner III>
  14. or enough information to understand what needs to be done.  My FIDOnet
  15. node number is 1:133/302.  My EGGnet address is 99:9000/6.
  16.  
  17.                                 Steve Antonoff
  18.                                 Atlanta, GA
  19.                                 August 8, 1990
  20.  
  21. ***********************************************************************
  22.  
  23.  O_RENUM.C Does message renumbering for Opus 1.1x+ in "straight" C.
  24.  No fancy low-level calls, will probably be slower than Bob Hartman's
  25.  but will work on anything.
  26.  
  27.  Fully released to the Opus community. Have fun, make it faster/better
  28.  just keep it free!
  29.                                          Doug Boone 119/5
  30.                                          P.O. Box 5108
  31.                                          Chico, CA 959528
  32.  
  33.  Thanks to Bob Hartman for providing code. Although I didn't use any of
  34.  his code, being able to understand the logic and procedures he used
  35.  were extremely important.
  36.  
  37.  ---------------------------------------------------------------------
  38. Pre-1.10    1/12/90    Steve Antonoff
  39.  Compiled with COMPACT model of TurboC
  40.  Added ECHO.CTL searching and command line
  41.         argument for SYSTEM directory
  42.  
  43. 1.10.ix.A    1/22/90    Steve Antonoff
  44.  Applied Bob Davis' fix for 1.MSG                1/22/90  Steve Antonoff
  45.     added "adopted" and "thanks" lines
  46. Added OPUS version number and COMPDATE
  47.  
  48. 1.10.ix.C    1/31/90    Steve Antonoff:
  49.  Added additional checks to prevent killing of 1.msg in echo areas
  50.  Added -T (threshhold) option
  51.  Changed fgetc/fputc to fread/fwrite for LASTREAD file
  52.  
  53. 1.10.ix.D    02/24/90 Steve Antonoff
  54.  Fixed error that occured if last message read was being deleted
  55.  Changed program name from RENUM to O_RENUM
  56.  
  57. 1.10.ix.E 02/25/90 Steve Antonoff
  58.  Fixed renumbering to include last message (bug introduced in .ix.D)
  59.  
  60. 1.10.ix.F 02/26/90 Steve Antonoff
  61.  Fixed processing for -N option to not require -R at the same time
  62.  
  63. 1.10.ix.G 03/06/90 Steve Antonoff
  64.  Fixed processing for 1.MSG to update high water mark properly
  65.  
  66. 1.10 3/13/90 Steve Antonoff
  67.  Reversed order for test on high water mark
  68.  Official release version for OPUS 1.10
  69.  
  70. 1.10A 3/17/90 Steve Antonoff
  71.     Fixed update of LASTREAD to reflect correct value (was off by 1)
  72.  
  73. 1.10B 3/19/90 Steve Antonoff
  74.   Added -W (write) and -A (automatic) options to write and read
  75.   renum parameters from RENUM.DAT in the OPUS SYSTEM path.
  76.  
  77. 1.10C 3/19/90 Steve Antonoff
  78.   Fixed -N to count 1.MSG in the count of messages kept below #
  79.  
  80.  
  81. 1.10D 3/25/90 Steve Antonoff
  82.   Suppressed RENUMBER and RELINK if -R is not specified
  83.  
  84. 1.10E 4/01/90 Steve Antonoff
  85.   -W only writes the parameters - doesn't do any renumbering
  86.   set exit() errorlevels to indicate error condition to DOS:
  87.  
  88.     0 Successful or no renumber based on threshhold
  89.     1 Neither area number nor name given
  90.     2 Insufficient memory for message data
  91.     3 Error getting system info from SYSTEM.DAT
  92.     4 Write of RENUM parameters requested - no other processing performed
  93.     5 Can't find message path
  94.     6 Insufficient memory for user file data
  95.     7 Message number exceeds requeste max
  96.     8 Help (no arguments given)
  97.  
  98. 1.10F 6/23/90 Steve Antonoff
  99.     "Neatened" up the status displays while running.
  100.     Added a display of the number of messages found.
  101.     Improved intelligence of command line parser to accept directory and
  102.     file names with or without an intervening space.
  103.  
  104. 1.13 6/30/90 Steve Antonoff
  105.     Converted to "sparse" array manipulation, using qsort() to sort
  106.     message array.  Thus, if an area has messages 1, 1000-1010, only 13
  107.     message slots will be used rather than 1011.  Slot 0 is not used
  108.     ever.
  109.     Changed message number displays from %4d to %5d, allowing a full
  110.     32K-1 to be displayed properly.
  111.  
  112. 1.13A 7/8/90 Steve Antonoff
  113.     Fixed bug in -M argument processing: 'M' was not listed in the switch
  114.     statement as a single parameter argument
  115.  
  116. 1.13B 7/28/90 Steve Antonoff
  117.     Added -V (verbose) option and changed display of message numbers and
  118.     user names to default to off (quiet mode)
  119.     Added -Q (quiet) option to surpress normal status messages
  120.     Added -C (change directory) for future version
  121.  
  122. 1.13C 7/31/90 Steve Antonoff
  123.     Changed test to allow -N option to allow -N=0,x
  124.     Fixed logic to use msg_count rather than max_msg in various places;
  125.     Use in_number and out_number rather than the index in various places
  126.         to accommodate sparse matrix
  127.  
  128. 1.13D 8/9/90 Steve Antonoff
  129.     Changed calls to fix_lastread and fix_user back to use new_max_msg,
  130.     which is correctly returned from relink.  1.13C incorrectly used
  131.     msg_count for these two routines, resulting in message counts for
  132.     lastread and user renumber.  The lastread/user lastread counters
  133.     are only adjusted if new_max_msg is not equal to max_msg, indicating
  134.     that some adjustment might be necessary.
  135.  
  136. 1.13E 8/31/90 Steve Antonoff
  137.     Added check for 4 byte LASTREAD file as used by MSGED.  Both pointers
  138.     are adjusted if a 4 byte file is found.
  139.  
  140. 1.13F 9/8/90 Steve Antonoff
  141.     1) Extended 1.13E changes to include variable length LASTREAD files
  142.     to accommodate other message handlers.  The LASTREAD file is treated
  143.     as a list of int, each int adjusted independently.
  144.     2) Corrected error in handling of QUIET mode: if QUIET was engaged,
  145.     message renumbering might have been disabled in certain circumstances.
  146.  
  147. 1.71  8/5/91 Doug Boone.
  148.  
  149.     Update for Opus 1.7x
  150.  
  151. ***************************************************************************/
  152. #include    <stdio.h>
  153. #include    <dos.h>
  154. #include    <string.h>
  155. #include    <ctype.h>
  156. #include    <io.h>
  157. #include    <stdlib.h>
  158. #ifdef __TURBOC__
  159. #include    <alloc.h>
  160. #include    <dir.h>
  161. #else
  162. #include    <malloc.h>
  163. #endif
  164. #include    <fcntl.h>
  165. #include <sys\types.h>
  166. #include    <sys\stat.h>
  167. #ifdef OS2
  168. #define INCL_GPI
  169. #define INCL_BASE
  170. #define INCL_DOS 
  171. #include <os2.h>
  172. #endif
  173. /*#include    "otoolkit.h"*/
  174. /*#include    "compdate.h" */
  175. #include    "newuser.h"
  176. #include    "system.h"
  177.  
  178. #define VERSION "1.71"
  179.  
  180. #define     MAX_USERS   24        /* Maximum # of users to update at once */
  181. #define        MAX_PATH    80      /* Maximum file path                    */
  182. #define        MAX_NAME    33        /* Maximum echo name                    */
  183.  
  184. #ifndef FALSE
  185. #define FALSE 0
  186. #define TRUE !FALSE
  187. #endif
  188.  
  189. /*------------------------------------------------------------------------*/
  190. /* Set of values to use with  "flags" to tell renum what to do            */
  191. /*------------------------------------------------------------------------*/
  192. #define     KILL_DAYS   0x0001
  193. #define     KILL_NUMBER 0x0002
  194. #define     KILL_RCVD   0x0004
  195. #define     KILL_SENT   0x0008
  196. #define     RENUMBER    0x0010
  197. #define        RELINK_MSG    0x0020
  198. #define     IS_ECHO     0x1000
  199. /*------------------------------------------------------------------------*/
  200. /* Message status flags                                                   */
  201. /*------------------------------------------------------------------------*/
  202. #define     ZAP         0x0001
  203. #define     EXISTS      0x0002
  204. #define     NOT_HERE    0x0000
  205. /*------------------------------------------------------------------------*/
  206. /* Return values                                                          */
  207. /*------------------------------------------------------------------------*/
  208. /*#define     ERROR       -1 */
  209. #define     SUCCESS     1
  210.  
  211. /*------------------------------------------------------------------------*/
  212. /* Used to generate dates                                                 */
  213. /*------------------------------------------------------------------------*/
  214.  
  215. #define YEAR_SHIFT      9
  216. #define MONTH_SHIFT     5
  217. #define    DOS_EPOCH        80
  218.  
  219. #ifndef ERROR
  220. #define ERROR   (-1)
  221. #endif
  222. /*------------------------------------------------------------------------*/
  223. /* The basic internal structure to keep track of messages                 */
  224. /*------------------------------------------------------------------------*/
  225. struct  a_msg
  226. {
  227.     int     status;            /* internal renum status for this message     */
  228.     int     in_number;        /* what was the original message number       */
  229.     int     out_number;        /* what is the output number going to be      */
  230.     int     how_old;        /* date_received date stamp                   */
  231.     int     uplink;            /* "there is a reply....."                    */
  232.     int     downlink;        /* "this is a reply to ......"                */
  233.     int     attr;            /* the message's attribute                    */
  234. };
  235.  
  236. /*------------------------------------------------------------------------*/
  237. /* Global Data                                                            */
  238. /*------------------------------------------------------------------------*/
  239. struct  a_msg   *msg;
  240. int        MAX_MSGS = 1024;        /* default max message area size        */
  241. char    msg_path[MAX_PATH];        /* the message area path                */
  242. char    echo_name[MAX_NAME];    /* the echo area name                    */
  243. /*int     flags = RELINK_MSG;*/        /* RENUM flags so we know what to do    */
  244. char    *msg_file_format = "%s%i.MSG";    /* Format for message file name    */
  245. int        months[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  246. int     area = -1;        /* What area number is being used    */
  247. char    echo_ctl_name[MAX_PATH],opus_sys_path[MAX_PATH];
  248. int        verbose = FALSE;
  249. int        quiet = FALSE;
  250. int        change_dir = FALSE;
  251. int     Opus_120 = FALSE;
  252.  
  253. struct flag_struct          /* RENUM flags so we know what to do    */
  254. {
  255.     unsigned threshhold:1;
  256.     unsigned kill_days:1;
  257.     unsigned kill_number:1;
  258.     unsigned kill_rcvd:1;
  259.     unsigned kill_sent:1;
  260.     unsigned renumber:1;
  261.     unsigned relink:1;
  262.     unsigned is_echo:1;
  263.     unsigned spare:8;
  264. };
  265.  
  266. struct renum_param            /* RENUM parameter structure            */
  267. {
  268.     struct flag_struct flags;
  269.     int    days;
  270.     int    keep_lo,keep_hi;
  271.     int min_delete;
  272. }renum,renum_from_file;
  273.  
  274. /*------------------------------------------------------------------------*/
  275. /* Procedure definitions                                                  */
  276. /*------------------------------------------------------------------------*/
  277.  
  278. void    fix_lastread(int);
  279. void     fix_users(int,int);
  280. int     relink(int);
  281. void    delete_msgs(int);
  282. int        kill_count(int);
  283. int        message_count(int);
  284. int     get_sys_info(int,char *);
  285. int     get_msg_info(int *);
  286. int     msg_age_as_of(int);
  287. void    no_parms(int,int);
  288. int     scan_echo_ctl(char *, char *, char *);
  289. int        proc_args(int, char **);
  290. void    show_params(int);
  291. int        read_param_data(int,char *);
  292. int        write_param_data(int,char *);
  293. #ifdef __TURBOC__
  294. int        msg_cmp(const void *,const void *);
  295. #else
  296. int        msg_cmp(struct a_msg *,struct a_msg *);
  297. #endif
  298. void    xprintf(const char *);
  299. /*--------------------------------------------------------------------------*/
  300. extern  long    get_msgpos(int,char *);
  301. extern  char  * pascal getstring(byte,int);
  302. void  fix_lread_dat(int);
  303. /*--------------------------------------------------------------------------*/
  304. void xprintf(const char *s)
  305. {
  306.     if (!quiet)
  307.         printf("%s",s);
  308. }
  309.  
  310. #ifdef __TURBOC__
  311. int    msg_cmp(const void *msg1,const void *msg2)
  312. {
  313.     struct    a_msg *m1,*m2;
  314.     m1 = (struct a_msg *)msg1;
  315.     m2 = (struct a_msg *)msg2;
  316.     return (m1->in_number - m2->in_number);
  317. }
  318. #else
  319. int    msg_cmp(struct a_msg *msg1,struct a_msg *msg2)
  320. {
  321.     return (msg1->in_number - msg2->in_number);
  322. }
  323. #endif
  324.  
  325. int add_slash(char *path)
  326. {
  327.     char last_char;
  328.  
  329.     last_char = path[strlen(path)-1];
  330.         if (last_char != '\\' && last_char != ':')
  331.             strcat(path,"\\");
  332.     return last_char;
  333. }
  334.  
  335. int main(int argc,char *argv[])
  336. {
  337.     int     i = 1;
  338.     int     j;
  339.     int     k;
  340. #ifdef OLDVERSION
  341.     int     days;            /* Number of days for deleting        */
  342.     int     keep_lo;
  343.     int     keep_hi;
  344.     int        min_delete=-1;
  345. #endif
  346.     int        killed_count=0;
  347.     int        write_data=0; /* 0 = no action, 1 = write data, 2 = read data*/
  348.     int     older;            /* Date stamp for older messages    */
  349.     int     max_msg;        /* Highest message number found        */
  350.     int        new_max_msg;    /* Highest message after renumbering    */
  351.     int        msg_count;        /* Number of messages found            */
  352.  
  353.     no_parms(argc-1,0);        /* give instructions or credit        */
  354.  
  355.     msg_path[0] = 0;        /* blast out msg_path                */
  356.     echo_name[0] = 0;
  357.     echo_ctl_name[0] = 0;
  358.     opus_sys_path[0] = 0;
  359.     renum.min_delete = 0;
  360.  
  361.     renum.flags.threshhold    =    FALSE;
  362.     renum.flags.kill_days     =     FALSE;
  363.     renum.flags.kill_number    =    FALSE;
  364.     renum.flags.kill_rcvd    =    FALSE;
  365.     renum.flags.kill_sent    =    FALSE;
  366.     renum.flags.renumber    =    FALSE;
  367.     renum.flags.relink        =    TRUE;
  368.     renum.flags.is_echo        =    FALSE;
  369.  
  370.     write_data = proc_args(argc,argv);
  371.     if (!(msg_path[0]) && (area==-1))
  372.     {
  373.         printf("Neither message area directory nor area number given\n");
  374.         exit(1);
  375.     }
  376.     if ( NULL ==
  377.         (msg = (struct a_msg *) calloc(sizeof(struct a_msg),MAX_MSGS) ) )
  378.     {
  379.         printf("Unable to allocate space for %d messages\n",MAX_MSGS);
  380.         exit(2);
  381.     }
  382.  
  383.     if (echo_ctl_name[0])
  384.     {
  385.         add_slash(echo_ctl_name);
  386.         strcat(echo_ctl_name,"ECHO.CTL");
  387.     }
  388.     if (opus_sys_path[0])
  389.         add_slash(opus_sys_path);
  390.     else
  391.         write_data = 0;    /* can't read or write without OPUS system path    */
  392.  
  393.     if (msg_path[0])
  394.     {
  395.         strcpy(echo_name,msg_path);
  396.         add_slash(msg_path);
  397.         area = scan_echo_ctl(msg_path,echo_name,echo_ctl_name);
  398.     }
  399.     if (!(msg_path[0]))         /* If the message path is no good..... */
  400.     {
  401.         if (ERROR == get_sys_info(area,opus_sys_path) )
  402.             exit(3);
  403.     }
  404.     if ((write_data & 2) && area > -1)
  405.     {
  406.         read_param_data(area,opus_sys_path);
  407.         proc_args(argc,argv);
  408.     }
  409.     show_params(write_data);
  410.     if ((write_data & 1) && area > -1)
  411.     {
  412.         write_param_data(area,opus_sys_path);
  413.         printf("Data written - O_RENUM terminating\n");
  414.         exit(4);
  415.     }
  416.     if (renum.flags.is_echo)
  417.         xprintf("Treating area as ECHOMAIL....\n");
  418.     i = strlen(msg_path) - 1;
  419.     if (msg_path[i] == '\\')
  420.         msg_path[i] = '\0';
  421.     if (access(msg_path,0))
  422.     {
  423.         printf("Can't find path %s\n\n",msg_path);
  424.         exit(5);
  425.     }
  426.     strcat(msg_path,"\\");
  427.    printf("Checking messages in %s\n",msg_path);
  428.  
  429.     max_msg = get_msg_info(&msg_count);
  430.  
  431.     if (!quiet)
  432.     {
  433.         printf("Max message number found: %d\n",max_msg);
  434.         printf("Number of messages found: %d\n",msg_count-1);
  435.         printf("Sorting message array...\n");
  436.     }
  437.     qsort(msg,(size_t)msg_count,sizeof (struct a_msg),msg_cmp);
  438.  
  439.     if (renum.flags.kill_sent)
  440.     {
  441.         xprintf("Marking messages that have been sent........\n");
  442.         for (i = 0; i<= msg_count; i++)
  443.             if (msg[i].attr & MSGSENT)
  444.                 msg[i].status = ZAP;
  445.     }
  446.  
  447.     if (renum.flags.kill_rcvd)
  448.     {
  449.         xprintf("Marking messages that have been received....\n");
  450.         for (i = 0; i<= msg_count; i++)
  451.             if (msg[i].attr & MSGREAD)
  452.                 msg[i].status = ZAP;
  453.     }
  454.  
  455.     if (renum.flags.kill_days)
  456.     {
  457.         xprintf("Marking old messages....\n");
  458.         older = msg_age_as_of(renum.days);
  459.         for (i = 1; i<= msg_count; i++)
  460.             if (msg[i].how_old < older)
  461.                 msg[i].status = ZAP;
  462.     }
  463.  
  464.     if (renum.flags.kill_number)
  465.     {
  466.         if (!quiet)
  467.             printf(
  468. "Marking messages after #%i and before the highest %i messages.....\n",
  469.             renum.keep_lo,renum.keep_hi);
  470.     }
  471.     else
  472.     {
  473.         renum.keep_hi = msg_count;
  474.         renum.keep_lo = 1;
  475.     }
  476.  
  477.     if (renum.flags.kill_number)
  478.     {
  479.         j = renum.keep_hi;
  480.         i = msg_count;
  481.         while (j > 0 && i > renum.keep_lo)
  482.         {
  483.             if (EXISTS == msg[i].status)
  484.                 j--;
  485.             i--;
  486.         }
  487.         if (renum.flags.is_echo)    /* don't kill 1.msg for echos        */
  488.         {
  489.             k = 2;
  490.             j = 1;                    /* but remember that we haven't!    */
  491.         }
  492.         else
  493.         {
  494.             k = 1;
  495.             j = 0;
  496.         }
  497.         while (j < renum.keep_lo && k <= i)
  498.         {
  499.             if (EXISTS == msg[k].status)
  500.                 j++;
  501.             k++;
  502.         }
  503.         for (j = k;j <= i;j++)
  504.             msg[j].status = ZAP;
  505.     }
  506.     killed_count = kill_count(msg_count);
  507.     if (renum.flags.threshhold && (killed_count < renum.min_delete) )
  508.     {
  509.         printf("Fewer than %i messages to delete (%i) - terminating\n",
  510.             renum.min_delete,killed_count);
  511.         exit(0);
  512.     }
  513.     if (!quiet)
  514.         printf("Killing %i messages....\n",killed_count);
  515.     delete_msgs(msg_count);
  516.     if (renum.flags.renumber)
  517.     {
  518.         new_max_msg = relink(msg_count);
  519.         if (new_max_msg != max_msg)
  520.         {
  521.             fix_lastread(new_max_msg);
  522.             if (area != -1) {
  523.                 if (Opus_120) {
  524.                     fix_lread_dat(new_max_msg);
  525.                    }
  526. /*               else   Uncomment this line for newer version*/
  527. /*                    if (area < 256)
  528.                         fix_users(new_max_msg,area); */
  529.                 }
  530.         }
  531.     }
  532.     exit(0);
  533.     return 0;
  534. }
  535.  
  536. /*------------------------------------------------------------------------*/
  537. /* Fix up LASTREAD in this area                                           */
  538. /*------------------------------------------------------------------------*/
  539. void fix_lastread(int max)
  540. {
  541.     char    full[MAX_PATH];
  542.     FILE    *infp;
  543.     int        last_msg;
  544.     int        i;
  545.     int     hit;
  546.     long    last_leng,last_cnt;
  547.  
  548.     sprintf(full,"%sLASTREAD",msg_path);
  549.     if ((infp = fopen(full,"r+b")) == NULL)
  550.         return;
  551.     fseek(infp,0L,SEEK_END);
  552.     last_leng = ftell(infp);
  553.     fseek(infp,0L,SEEK_SET);
  554.     if (verbose || !quiet)
  555.         printf("Updating %s:\n",full);
  556.     for (last_cnt = 0 ; last_cnt < last_leng ; last_cnt += 2)
  557.     {
  558.         hit = FALSE;
  559.         fseek(infp,last_cnt,SEEK_SET);
  560.         fread(&last_msg,2,1,infp);
  561.         if (last_msg > 0)
  562.         {
  563.             if (verbose || !quiet)
  564.                 printf(" %d ->",full,last_msg);
  565.             for (i = max; i >= 1 && !hit ; i--)
  566.             {
  567.                 if (msg[i].in_number <= last_msg)
  568.                 {
  569.                     last_msg = msg[i].out_number;
  570.                     hit = TRUE;
  571.                 }
  572.             }
  573.             if (!hit)
  574.                 last_msg = 0;
  575.             fseek(infp,last_cnt,SEEK_SET);
  576.             fwrite(&last_msg,2,1,infp);
  577.             if (verbose || !quiet)
  578.             {
  579.                 printf("%d\n",last_msg);
  580.             }
  581.         }
  582.     }
  583.     fclose(infp);
  584.     return;
  585. }
  586. /*------------------------------------------------------------------------*/
  587. /* Fix up user records, resetting message areas as needed                 */
  588. /*------------------------------------------------------------------------*/
  589. void fix_users(int high,int area)
  590. {
  591.     struct  _usr    *auser;
  592.     int     i;
  593.     int     j;
  594.     int     k;
  595.     int     hit=FALSE;
  596.     int        user_no = 0;
  597.     FILE    *infp;
  598.  
  599.  
  600.     if ( (auser =
  601.       (struct _usr *)calloc(MAX_USERS, sizeof (struct _usr) ) ) ==
  602.       NULL)
  603.     {
  604.         printf("Unable to allocate memory for user file buffer\n");
  605.         exit(6);
  606.     }
  607.     if ((infp = fopen("USER.DAT","r+b")) == NULL)
  608.     {
  609.         printf("\nCouldn't find USER.DAT!!\n");
  610.         return;
  611.     }
  612.     xprintf("Updating USER records..........\n");
  613.     while ((k = fread(auser,sizeof(struct _usr),MAX_USERS,infp)) > 0)
  614.     {
  615.         for (i = 0; i < k; i++)
  616.         {
  617.             user_no++;
  618.             if (auser[i].lastmsg[area] > 0)
  619.             {
  620.                 hit = FALSE;
  621.                 for (j = high; j >= 1 && !hit; j--)
  622.                 {
  623.                     if (msg[j].in_number <= auser[i].lastmsg[area])
  624.                     {
  625.                         if (verbose && !quiet)
  626.                             printf("\r%5d -> %5d: (%d) %-40.40s",
  627.                                 auser[i].lastmsg[area],msg[j].out_number,
  628.                                 user_no,auser[i].name);
  629.                         auser[i].lastmsg[area] = msg[j].out_number;
  630.                         hit = TRUE;
  631.                     }
  632.                 }
  633.                 if (!hit)
  634.                     auser[i].lastmsg[area] = 1;
  635.             }
  636.         }
  637.         fseek(infp,-((long) (k * sizeof(struct _usr))),SEEK_CUR);
  638.         fwrite(auser,sizeof(struct _usr),k,infp);
  639.     };
  640.     fclose(infp);
  641.     free(auser);
  642.     printf("\n");
  643.     return;
  644. }
  645.  
  646. /*------------------------------------------------------------------------*/
  647. /* Relink the replies in the message headers                              */
  648. /*------------------------------------------------------------------------*/
  649. int relink(int high)
  650. {
  651.     int     i,hit;
  652.     int     j = 1;
  653.     int     low = 1;
  654.     char    new[MAX_PATH];
  655.     char    old[MAX_PATH];
  656.     FILE    *infp;
  657.     struct  _msg    amsg;
  658.  
  659.     if (!quiet)
  660.         printf("Renumbering %sMessages........\n",
  661.             (renum.flags.relink) ?"& Relinking ":"");
  662.  
  663.     if (renum.flags.is_echo)
  664.     {
  665.         low = 2;
  666.         j = 2;
  667.     }
  668. /*------------------------------------------------------------------------*/
  669. /* This is where renumbering really takes place, finding the messages     */
  670. /* that are still marked as EXISTS and crunching them down.               */
  671. /*------------------------------------------------------------------------*/
  672.     for (i = low; i <= high; i++)
  673.     {
  674.         if (EXISTS == msg[i].status)
  675.         {
  676.             msg[j].status       = msg[i].status;
  677.             msg[j].in_number    = msg[i].in_number;
  678.             msg[j].out_number   = j;
  679.             msg[j].how_old      = msg[i].how_old;
  680.             msg[j].uplink       = msg[i].uplink;
  681.             msg[j].downlink     = msg[i].downlink;
  682.             msg[j].attr         = msg[i].attr;
  683.             j++;
  684.         }
  685.     }
  686. /*------------------------------------------------------------------------*/
  687. /* Now we've packed down the msg array and found the new highest message  */
  688. /* so begin the process of re-linking the replies                         */
  689. /*------------------------------------------------------------------------*/
  690.     high = j;
  691.     if (high)
  692.         high--;
  693.     if (renum.flags.is_echo)
  694.     {
  695.         if (msg[1].status > 0)
  696.             msg[1].status = EXISTS;
  697.         if (msg[1].downlink > 0)         /* Handle 1.MSG for echoes */
  698.         {
  699.             hit = FALSE;
  700.             for (j = high; j > 0 && !hit ;j--)    /* High Water Mark    */
  701.             {
  702.                 if (msg[j].in_number <= msg[1].downlink)
  703.                 {
  704.                     msg[1].downlink = msg[j].out_number;
  705.                     j = high;
  706.                     hit = TRUE;
  707.                 }
  708.             }
  709.         }
  710.         if (msg[1].uplink > 0)
  711.         {
  712.             hit = FALSE;
  713.             for (j = high; j > 0 && !hit; j--)
  714.             {
  715.                 if (msg[j].in_number == msg[1].uplink)
  716.                 {
  717.                     msg[1].uplink = msg[j].out_number;
  718.                     j = high;
  719.                     hit = TRUE;
  720.                 }
  721.             }
  722.         }
  723.         sprintf(new,"%s1.MSG",msg_path);
  724.         infp = fopen(new,"r+b");
  725.         fread(&amsg,sizeof(struct _msg),1,infp);
  726.         amsg.reply = msg[1].downlink;
  727.         amsg.up = msg[1].uplink;
  728.         fseek(infp,0L,SEEK_SET);
  729.         fwrite(&amsg,sizeof(struct _msg),1,infp);
  730.         fclose(infp);
  731.  
  732.     }        /* End of special handling for message #1 */
  733.  
  734.     for (i = low; i <= high; i++)
  735.     {
  736.         if (msg[i].downlink > 0)
  737.         {
  738.             hit = FALSE;
  739.             for (j = low; j < i && !hit; j++)
  740.             {
  741.                 if (msg[j].in_number == msg[i].downlink)
  742.                 {
  743.                     msg[i].downlink = j;
  744.                     hit = TRUE;
  745.                 }
  746.             }
  747.         }
  748.         if (msg[i].uplink > 0)
  749.         {
  750.             hit = FALSE;
  751.             for (j = i; j <= high && !hit; j++)
  752.             {
  753.                 if (msg[j].in_number == msg[i].uplink)
  754.                 {
  755.                     msg[i].uplink = j;
  756.                     hit = TRUE;
  757.                 }
  758.             }
  759.         }
  760.     }
  761. /*------------------------------------------------------------------------*/
  762. /* Rename the messages                                                    */
  763. /*------------------------------------------------------------------------*/
  764.     for (i = low; i <= high; i++)
  765.     {
  766.         if (msg[i].in_number != i)
  767.         {
  768.             sprintf(new,msg_file_format,msg_path,msg[i].out_number);
  769.             sprintf(old,msg_file_format,msg_path,msg[i].in_number);
  770.             if (verbose && !quiet)
  771.                 printf("\r%5d -> %5d",msg[i].in_number,msg[i].out_number);
  772.             if (rename(old,new) != 0)
  773.             {
  774.                 unlink(new);
  775.                 rename(old,new);
  776.             }
  777.             if ( (msg[i].uplink || msg[i].downlink) && (renum.flags.relink) )
  778.             {
  779.                 infp = fopen(new,"r+b");
  780.                 fread(&amsg,sizeof(struct _msg),1,infp);
  781.                 amsg.reply = msg[i].downlink;
  782.                 amsg.up = msg[i].uplink;
  783.                 fseek(infp,0L,SEEK_SET);
  784.                 fwrite(&amsg,sizeof(struct _msg),1,infp);
  785.                 fclose(infp);
  786.             }
  787.         }
  788.     }
  789.     if (verbose && !quiet)
  790.         printf("\n");
  791.     return(high);        /* Return the new max_msg                         */
  792. }
  793.  
  794. /*------------------------------------------------------------------------*/
  795. /* Delete all the messages who have a status of ZAP                       */
  796. /*------------------------------------------------------------------------*/
  797. void delete_msgs(int high)
  798. {
  799.     char    full[MAX_PATH];
  800.     int     i;
  801.     int     j = 1;
  802.  
  803.     if (renum.flags.is_echo)
  804.         j = 2;
  805.     for (i = j;i <= high;i++)
  806.     {
  807.         if (ZAP == msg[i].status)
  808.         {
  809.             if (verbose && !quiet)
  810.                 printf("Kill %5d\r",msg[i].in_number);
  811.             sprintf(full,msg_file_format,msg_path,msg[i].in_number);
  812.             unlink(full);
  813.         }
  814.     }
  815.     if (verbose && !quiet)
  816.         printf("\n");
  817.     return;
  818. }
  819. /*------------------------------------------------------------------------*/
  820. /* Read the SYSTEM*.DAT path, only works with Opus 1.10!                  */
  821. /*------------------------------------------------------------------------*/
  822. int get_sys_info(int area,char *opus_sys_path)
  823. {
  824.     struct      _sys    one_sys;
  825.     FILE    *handle;
  826.     char    sys_path[MAX_PATH];
  827.     struct  _msgsys asys;
  828.     long    f_pos;
  829.     int     fh;
  830.     char    *junk;
  831.  
  832.     if (Opus_120) {
  833.         if ((f_pos = get_msgpos(area,opus_sys_path)) < 0L)
  834.             return(ERROR);
  835.         sprintf(sys_path,"%sSYSMSG.DAT",opus_sys_path);
  836.         if ((fh = open(sys_path,O_RDONLY|O_BINARY)) < 0) {
  837.             printf("\nFailed to open %s\n",sys_path);
  838.             return(ERROR);
  839.             }
  840.         lseek(fh,f_pos,SEEK_SET);
  841.         read(fh,(char*)&asys,sizeof(struct _msgsys));
  842.         junk = getstring(asys.Path_Len,fh);
  843.         strcpy(msg_path,junk);
  844.         free(junk);
  845.         close(fh);
  846.         if (asys.Attrib & ECHOMAIL)
  847.             renum.flags.is_echo = TRUE;
  848.         return(SUCCESS);
  849.         }
  850. /*--------------------------------------------------------------------------*/
  851.     sprintf(sys_path,"%sSYSTEM%02X.DAT",opus_sys_path,area);
  852.  
  853.     if ((handle = fopen(sys_path,"rb")) == NULL)
  854.     {
  855.         printf("Couldn't open %s!!\n",sys_path);
  856.         return(ERROR);
  857.     }
  858.     if ((fread(&one_sys,sizeof(struct _sys),1,handle)) < 0)
  859.     {
  860.         printf("Error reading %s!!\n",sys_path);
  861.         fclose(handle);
  862.         return(ERROR);
  863.     }
  864.  
  865.     strcpy(msg_path,(char *)one_sys.msgpath);
  866.     fclose(handle);
  867.     if (one_sys.attrib & ECHOMAIL)
  868.         renum.flags.is_echo = TRUE;
  869.     return(SUCCESS);
  870. }
  871. /*------------------------------------------------------------------------*/
  872. /* Read the message headers and load up the msg[] array                   */
  873. /*------------------------------------------------------------------------*/
  874. int get_msg_info(int *count)
  875. {
  876.     struct  _msg    amsg;
  877.     char    fullpath[MAX_PATH];
  878.     FILE    *handle;
  879. #ifdef __TURBOC__
  880.     struct  ffblk   ffblk;
  881. #elif OS2
  882.    HDIR        hdir;
  883.    USHORT      usSearch;
  884.    FILEFINDBUF findbuf;
  885. #else
  886.    struct  find_t  ffblk;
  887. #endif
  888.     int     done;
  889.     int     i;
  890.     int     high_msg = 0;
  891.  
  892.     *count = 1;
  893.     sprintf(fullpath,"%s*.MSG",msg_path);
  894. #ifdef __TURBOC__
  895.     done = findfirst(fullpath,&ffblk,0);
  896. #elif OS2
  897.    DosFindFirst(fullpath,&hdir,0x0017,&findbuf,sizeof(findbuf),&usSearch,0L);
  898.     if (usSearch)
  899.         done = 0;
  900.     else
  901.         done = 1;
  902.     printf("\nPath: %s Result: %s %x %x",fullpath,findbuf.achName,usSearch,done);
  903. #else
  904.     done = _dos_findfirst(fullpath,_A_NORMAL,&ffblk);
  905. #endif
  906.  
  907.     printf("Checking:\n");
  908.     while (!done) {
  909. #ifdef __TURBOC__
  910.         i = atoi(ffblk.ff_name);
  911. #elif OS2
  912.       i = atoi(findbuf.achName);
  913.     printf("\nFile: %s  Done = %x %x",
  914.         findbuf.achName,done,usSearch);
  915. #else
  916.     i = atoi(ffblk.name);
  917. #endif
  918.         if (i > MAX_MSGS)
  919.         {
  920.             printf("Message number %d exceeds max limit\n",i);
  921.             exit(7);
  922.         }
  923.         sprintf(fullpath,msg_file_format,msg_path,i);
  924.         if ((handle = fopen(fullpath,"rb")) == NULL)
  925.             msg[i].status = NOT_HERE;
  926.         else
  927.         {
  928.             if ((fread(&amsg,sizeof(struct _msg),1,handle)) < 0)
  929.                 msg[i].status = ZAP; /* this must be a bogus message, no header */
  930.             else
  931.             {
  932.                 if (verbose && !quiet)
  933.                     printf("%5d\r",i);
  934.                 msg[*count].status = EXISTS;
  935.                 msg[*count].in_number = i;
  936.                 msg[*count].uplink = amsg.up;
  937.                 msg[*count].downlink = amsg.reply;
  938.                 msg[*count].attr = amsg.attr;
  939.                 msg[*count].how_old = amsg.date_arrived.date;
  940.             }
  941.             if (high_msg < i)
  942.                 high_msg = i;
  943.             fclose(handle);
  944.         }
  945.         (*count)++;
  946. #ifdef __TURBOC__
  947.         done = findnext(&ffblk);
  948. #elif OS2
  949.       done = DosFindNext(hdir,&findbuf,sizeof(findbuf),&usSearch);
  950.     if (usSearch)
  951.         done = 0;
  952.     else
  953.         done = 1;
  954. #else
  955.         done = _dos_findnext(&ffblk);
  956. #endif
  957.     };
  958.     if (verbose && !quiet)
  959.         printf("\n");
  960.     return(high_msg);
  961. }
  962.  
  963. /*------------------------------------------------------------------------*/
  964. /* Work out what the date stamp would have been on the date (how_old) ago */
  965. /*------------------------------------------------------------------------*/
  966. int msg_age_as_of(int kill_date)
  967. {
  968.     int     day;
  969.     int     month;
  970.     int     year;
  971.     int     check;
  972. #ifdef OS2
  973.    struct   _DATETIME   date;
  974.  
  975.  
  976.    DosGetDateTime(&date);
  977.  
  978.    month = date.month;
  979.    day = date.day;
  980.    year = date.year;
  981. #else
  982.     union   REGS    inregs,outregs;
  983.  
  984.     inregs.h.ah = 0x2a;
  985.     intdos(&inregs,&outregs);
  986.     year = outregs.x.cx;
  987.     month = outregs.h.dh;
  988.     day = outregs.h.dl;
  989. #endif
  990.  
  991.     while (kill_date > 0)
  992.     {
  993.         if (day > kill_date)
  994.         {
  995.             day -= kill_date;
  996.             kill_date = 0;
  997.         }
  998.         else
  999.         {
  1000.             months[1] = (year % 4 ? 28 : 29); /* Leap years through 2099 */
  1001.             if (month == 1) /* move back to previous year    */
  1002.             {
  1003.                 if (kill_date >= 31)
  1004.                     kill_date -= 31;
  1005.                 else
  1006.                 {
  1007.                     day = 31 + day - kill_date;
  1008.                     kill_date = 0;
  1009.                 }
  1010.                 year--;
  1011.                 month = 12;
  1012.             }
  1013.             else
  1014.             {
  1015.                 if (kill_date >= months[month-2])
  1016.                     kill_date -= months[month-2];
  1017.                 else
  1018.                 {
  1019.                     day = months[month-2] + day - kill_date;
  1020.                     kill_date = 0;
  1021.                 }
  1022.                 month--;
  1023.             }
  1024.         }
  1025.     }
  1026. /*------------------------------------------------------------------------*/
  1027.     if (!quiet)
  1028.         printf("Kill older than: %02d-%02d-%4d\n",month,day,year);
  1029. /*------------------------------------------------------------------------*/
  1030.     year = (year % 100);
  1031.     year -= DOS_EPOCH;
  1032.     check = year << YEAR_SHIFT;
  1033.     check += month << MONTH_SHIFT;
  1034.     check += day;
  1035.     return(check);
  1036. }
  1037.  
  1038. /*------------------------------------------------------------------------*/
  1039. /* Your basic help and exit messages                                      */
  1040. /*------------------------------------------------------------------------*/
  1041. void no_parms(int argc,int arg_char)
  1042. {
  1043.     printf("\n\n"
  1044.         "O_RENUM %s %s - adopted by Steve Antonoff, 133/302\n"
  1045.         "Thanks to Bob Hartman, Doug Boone and Bob Davis.\n",
  1046.         VERSION,__DATE__);
  1047.     if (argc > 0)
  1048.         return;
  1049.     if (argc < 0)
  1050.         printf("\nError detected in command option: %c\n",arg_char);
  1051.     printf(
  1052. "\n"
  1053. "Use as O_RENUM [-K] [-N #1 #2] [-D ##] [-S] [-M #] [-F] [-E path]\n"
  1054. "     [-O path] [-T #] [-Q] [-V] [-R] [#|path|conf]\n"
  1055. "\n"
  1056. "-2 .............. Opus 1.7x!\n"
  1057. "-K .............. Kill received messages\n"
  1058. "-S .............. Delete messages that have already been sent\n"
  1059. "-N #1 #2 ........ Keep the first #1 messages and the last #2 messages\n"
  1060. "-D ## ........... Kill message more than ## days old\n"
  1061. "-M # ............ Maximum number of messages to handle (100-4500)\n"
  1062. "-F .............. Fast renum (don't relink message chains)\n"
  1063. "-E path ......... Path (disk:\\dir) to ECHO.CTL\n"
  1064. "-O path ......... Path (disk:\\dir) to OPUS SYSTEM??.DAT files\n"
  1065. "-T # ............ Threshhold (kill only if more than # msgs to kill)\n"
  1066. "-Q .............. Quiet mode (few displays)\n"
  1067. "-V .............. Verbose mode (message count & user names displayed)\n"
  1068. "-R .............. Renumber the messages\n"
  1069. "-W .............. Write parameters to RENUM.DAT and terminate\n"
  1070. "-A .............. Automatic renum (use data in RENUM.DAT\n"
  1071. "#/path/conf ..... Area number, path or conference name (tag) for messages\n"
  1072. "-W and -A require an area number, either from the command line or from\n"
  1073. "ECHO.CTL; both require an OPUS SYSTEM PATH (-o)\n"
  1074. "\n"
  1075. "Commands and parameters may be separated by spaces or they can be run\n"
  1076. "together, or they can be separated by \"=\" and the -N option can use a\n"
  1077. "comma to separte the two numbers.\n");
  1078.     exit(8);
  1079. }
  1080.  
  1081. int scan_echo_ctl(char *msg_path,char *area_name,char *echo_ctl_path)
  1082. {
  1083.     FILE    *ctl;
  1084.     int        areanum;
  1085.     char    echo_path[MAX_PATH];
  1086.     char    echo_name[MAX_NAME];
  1087.     char    buffer[256];
  1088.  
  1089.     if (!quiet)
  1090.         printf("Scanning %s for echo area directory %s...\n",
  1091.             echo_ctl_path,msg_path);
  1092.     if ( ( ctl = fopen(echo_ctl_path,"rt") ) == NULL )
  1093.     {
  1094.         printf("%s not found.....\n",echo_ctl_path);
  1095.         return -1;
  1096.     }
  1097.     while (!feof(ctl))
  1098.     {
  1099.         if (fgets(buffer,255,ctl))
  1100.         {
  1101.             sscanf(buffer,"%d %s %s",&areanum,echo_path,echo_name);
  1102.             if ( !stricmp(echo_path,msg_path ) ||
  1103.                  !stricmp(echo_name,area_name) )
  1104.             {
  1105.                 if (!quiet)
  1106.                     printf("Found: area #%d.....\n",areanum);
  1107.                 fclose(ctl);
  1108.                 msg_path[0] = 0;
  1109.                 return areanum;
  1110.             }
  1111.         }
  1112.     }
  1113.     printf("%s (%s) not found.....\n",msg_path,area_name);
  1114.     return -1;
  1115. }
  1116.  
  1117. int kill_count(int msg_count)
  1118. {
  1119.     int i,kill=0;
  1120.  
  1121.     xprintf("Counting messages to be killed....\n");
  1122.     if ( (renum.flags.is_echo) && msg[1].status == ZAP)
  1123.         msg[1].status = EXISTS;
  1124.     for (i=1 ; i <= msg_count ; i++)
  1125.         if (msg[i].status == ZAP)
  1126.             kill++;
  1127.     return kill;
  1128. }
  1129.  
  1130. /**************************************************************************/
  1131.  
  1132. int proc_args(int argc, char *argv[])
  1133. {
  1134.     int arg=1,write_data=0;
  1135.     char *arg_s,*arg_data1,*arg_data2;
  1136.     static int first=TRUE;
  1137.  
  1138.     if (first)
  1139.     {
  1140.         printf("Processing command line arguments....\n");
  1141.     }
  1142.     while (arg<argc)
  1143.     {
  1144.         strupr(argv[arg]);
  1145.         arg_s = argv[arg];
  1146.         if (*arg_s == '-' || *arg_s == '/')
  1147.         {
  1148.             ++arg_s;
  1149.             arg_data1 = arg_s + 1;
  1150.             if (*arg_data1 == '=')
  1151.                 arg_data1++;
  1152.             arg_data2 = arg_data1;
  1153.             while (*arg_data2 && *arg_data2 != ',')
  1154.                 arg_data2++;
  1155.             if (*arg_data2 == ',' || *arg_data2 == '=')
  1156.                 arg_data2++;
  1157.             switch (*arg_s)     /* group options:
  1158.                                     no parameters,
  1159.                                     one parameter,
  1160.                                     two parameters    */
  1161.             {
  1162.                 case    'K':    /* no parameters    */
  1163.                 case    'S':
  1164.                 case    'F':
  1165.                 case    'R':
  1166.                 case    'W':
  1167.                 case    'A':
  1168.                 case    'V':
  1169.                 case    'Q':
  1170.                 case    'C':
  1171.                     break;
  1172.                 case    'D':    /* one parameter    */
  1173.                 case    'T':
  1174.                 case    'E':
  1175.                 case    'O':
  1176.                 case    'M':
  1177.                 case    'N':    /* two parameters    */
  1178.                     if (!(*arg_data1) )    /* no parameters within arg    */
  1179.                     {
  1180.                         arg++;
  1181.                         arg_data1 = argv[arg];
  1182.                         arg_data2 = arg_data1;
  1183.                         while (*arg_data2 && *arg_data2 != ',')
  1184.                             arg_data2++;
  1185.                         if (*arg_data2 == ',' || *arg_data2 == '=')
  1186.                             arg_data2++;
  1187.                     }
  1188.  
  1189.                     if (*arg_s == 'N')    /* only two parameter option    */
  1190.                     {
  1191.                         if (!(*arg_data2) )    /* no second parameter    */
  1192.                         {
  1193.                             arg++;
  1194.                             arg_data2 = argv[arg];
  1195.                         }
  1196.                     }
  1197.                     break;
  1198.             }
  1199.             switch(*arg_s)
  1200.             {
  1201.                 case '2':
  1202.                     Opus_120 = TRUE;
  1203.                     break;
  1204.                 case 'V':
  1205.                     verbose = TRUE;
  1206.                     break;
  1207.                 case 'Q':
  1208.                     quiet = TRUE;
  1209.                     break;
  1210.                 case 'C':
  1211.                     change_dir = TRUE;
  1212.                     break;
  1213.                 case 'N':
  1214.                     renum.keep_lo = atoi(arg_data1);
  1215.                     renum.keep_hi = atoi(arg_data2);
  1216.                     renum.flags.kill_number = TRUE;
  1217.                     if (renum.keep_hi <= 0 || renum.keep_lo < 0)
  1218.                         no_parms(-1,*arg_s);
  1219.                     break;
  1220.  
  1221.                 case 'R':
  1222.                     renum.flags.renumber = TRUE;
  1223.                     break;
  1224.  
  1225.                 case 'D':
  1226.                     renum.days = atoi(arg_data1);
  1227.                     renum.flags.kill_days = TRUE;
  1228.                     if (renum.days <= 0)
  1229.                         no_parms(-1,*arg_s);
  1230.                     break;
  1231.  
  1232.                 case 'K':
  1233.                     renum.flags.kill_rcvd = TRUE;
  1234.                     break;
  1235.  
  1236.                 case 'S':
  1237.                     renum.flags.kill_sent = TRUE;
  1238.                     break;
  1239.  
  1240.                 case 'E':
  1241.                     if (first)
  1242.                     {
  1243.                         if (!(*arg_data1))
  1244.                             no_parms(-1,*arg_s);
  1245.                         strcpy(echo_ctl_name,arg_data1);
  1246.                     }
  1247.                     break;
  1248.  
  1249.                 case 'O':
  1250.                     if (first)
  1251.                     {
  1252.                         if (!(*arg_data1))
  1253.                             no_parms(-1,*arg_s);
  1254.                         strcpy(opus_sys_path,arg_data1);
  1255.                     }
  1256.                     break;
  1257.  
  1258.                 case    'M':
  1259.                     MAX_MSGS = atoi(arg_data1);
  1260.                     if (MAX_MSGS == 0)
  1261.                         no_parms(-1,*arg_s);
  1262.                     if (MAX_MSGS < 100)
  1263.                         MAX_MSGS = 100;
  1264.                     if (MAX_MSGS > 4500)
  1265.                         MAX_MSGS = 4500;
  1266.                     break;
  1267.  
  1268.                 case    'T':
  1269.                     renum.min_delete = atoi(arg_data1);
  1270.                     if (renum.min_delete <= 0)
  1271.                         no_parms(-1,*arg_s);
  1272.                     renum.flags.threshhold = TRUE;
  1273.                     break;
  1274.  
  1275.                 case    'F':
  1276.                     renum.flags.relink = FALSE;
  1277.                     break;
  1278.  
  1279.                 case    'W':
  1280.                     write_data += 1;
  1281.                     break;
  1282.  
  1283.                 case    'A':
  1284.                     write_data += 2;
  1285.                     break;
  1286.             }
  1287.         }
  1288.         else
  1289.         {
  1290.             if (first)
  1291.             {
  1292.                 if (isdigit(*argv[arg]) > 0)    /* is this an area number? */
  1293.                     area = atoi(argv[arg]);
  1294.                 else
  1295.                     strcpy(msg_path,argv[arg]);    /* must be just a path         */
  1296.             }
  1297.         }
  1298.         arg++;
  1299.     }
  1300.     first = FALSE;
  1301.     return (write_data);
  1302. }
  1303.  
  1304. /**************************************************************************/
  1305.  
  1306. void show_params(int write_data)
  1307. {
  1308.     char    *on="ON",*off="OFF";
  1309.     if (quiet)
  1310.         return;
  1311.     printf("\nWriting parameters: %s",write_data==1?on:off);
  1312.     printf("\nReading parameters: %s",write_data==2?on:off);
  1313.     printf("\nThreshhold:         %s",renum.flags.threshhold?on:off);
  1314.     if (renum.flags.threshhold)
  1315.         printf("  %d messages minimum",renum.min_delete);
  1316.     printf("\nDelete by days:     %s",renum.flags.kill_days?on:off);
  1317.     if (renum.flags.kill_days)
  1318.         printf("  %d days old or older",renum.days);
  1319.     printf("\nKill by Msg Number: %s",renum.flags.kill_number?on:off);
  1320.     if (renum.flags.kill_number)
  1321.         printf("  Leave first %d and last %d messages",
  1322.             renum.keep_lo,renum.keep_hi);
  1323.     printf("\nRelinking:          %s",renum.flags.relink?on:off);
  1324.     printf("\nRenumbering:        %s",renum.flags.renumber?on:off);
  1325.     printf("\nKill Sent:          %s",renum.flags.kill_sent?on:off);
  1326.     printf("\nKill Rcvd:          %s",renum.flags.kill_rcvd?on:off);
  1327.     if (*opus_sys_path)
  1328.         printf("\nOPUS System Path:   %s",opus_sys_path);
  1329.     if (*echo_ctl_name)
  1330.         printf("\nECHO.CTL Name:      %s",echo_ctl_name);
  1331.     printf("\nMessage path:       %s",msg_path);
  1332.     printf("\n");
  1333. }
  1334.  
  1335. int read_param_data(int area,char *opus_sys_path)
  1336. {
  1337.     FILE    *handle;
  1338.     char    sys_path[MAX_PATH];
  1339.  
  1340.     sprintf(sys_path,"%sRENUM.DAT",opus_sys_path);
  1341.  
  1342.     if ((handle = fopen(sys_path,"rb")) == NULL)
  1343.     {
  1344.         printf("Couldn't open %s!!\n",sys_path);
  1345.         return(ERROR);
  1346.     }
  1347.     fseek(handle,(long)area * sizeof(struct renum_param),SEEK_SET);
  1348.     if ((fread(&renum_from_file,sizeof(struct renum_param),1,handle)) < 0)
  1349.     {
  1350.         printf("Error reading %s!!\n",sys_path);
  1351.         fclose(handle);
  1352.         return(ERROR);
  1353.     }
  1354.  
  1355.     memcpy(&renum,&renum_from_file,sizeof(struct renum_param));
  1356.     fclose(handle);
  1357.     return(SUCCESS);
  1358. }
  1359.  
  1360. int write_param_data(int area,char *opus_sys_path)
  1361. {
  1362.     FILE    *handle;
  1363.     char    sys_path[MAX_PATH];
  1364.     int        area_no;
  1365.  
  1366.  
  1367.     sprintf(sys_path,"%sRENUM.DAT",opus_sys_path);
  1368.  
  1369.     if (access(sys_path,0))
  1370.     {
  1371.         if ( (handle = fopen(sys_path,"w+b") ) == NULL)
  1372.         {
  1373.             printf("Couldn't create %s!!\n",sys_path);
  1374.             return (ERROR);
  1375.         }
  1376.         for (area_no = 0 ; area_no < 256 ; area_no++)
  1377.         {
  1378.             if ((fwrite(&renum,sizeof(struct renum_param),1,handle)) < 0)
  1379.             {
  1380.                 printf("Error initializing %s!!\n",sys_path);
  1381.                 return(ERROR);
  1382.             }
  1383.         }
  1384.         fclose(handle);
  1385.     }
  1386.  
  1387.     if ( ( handle = fopen(sys_path,"r+b") ) == NULL)
  1388.     {
  1389.         printf("Couldn't open %s!!\n",sys_path);
  1390.         return(ERROR);
  1391.     }
  1392.     fseek(handle,(long)area * sizeof(struct renum_param),SEEK_SET);
  1393.     if ((fwrite(&renum,sizeof(struct renum_param),1,handle)) < 0)
  1394.     {
  1395.         printf("Error writing %s!!\n",sys_path);
  1396.         fclose(handle);
  1397.         return(ERROR);
  1398.     }
  1399.  
  1400.     fclose(handle);
  1401.     return(SUCCESS);
  1402. }
  1403.  
  1404. void  fix_lread_dat(int high)
  1405. {
  1406.     int     infh;
  1407.     int     outfh;
  1408.     int     hit;
  1409.     int        j;
  1410.     struct  _lmr      lreads;
  1411.     char    old_name[80];
  1412.     char    new_name[80];
  1413.  
  1414.     strcpy(old_name,msg_path);
  1415.     strcpy(new_name,msg_path);
  1416.     strcat(old_name,"LREAD.OLD");
  1417.     strcat(new_name,"LREAD.DAT");
  1418.  
  1419.    if (!quiet)
  1420.        printf("\nUpdating %s",old_name);
  1421.     unlink(old_name);
  1422.     rename(new_name,old_name);
  1423.  
  1424.     infh = open(old_name,O_BINARY|O_RDONLY);
  1425.     outfh = open(new_name,O_BINARY|O_WRONLY|O_CREAT,S_IWRITE|S_IREAD);
  1426.  
  1427.     while ((read(infh,(char *)&lreads,sizeof(struct _lmr))) == sizeof(struct _lmr)) {
  1428.         hit = 0;
  1429.         for (j = high; j > 1 && hit != 3; j--) {
  1430.             if (msg[j].in_number <= lreads.last_msg) {
  1431.                 lreads.last_msg = j;
  1432.                 hit |= 0x01;
  1433.                 }        /* End of success handling */
  1434.             if (msg[j].in_number <= lreads.high_msg) {
  1435.                 lreads.high_msg = j;
  1436.                 hit |= 0x02;
  1437.                 }
  1438.             }        /* End of for() loop */
  1439.         if (!hit)
  1440.             continue;
  1441.         if (!(hit & 0x02))
  1442.             lreads.high_msg = lreads.last_msg;
  1443.         if (!(hit & 0x01))
  1444.             lreads.last_msg = lreads.high_msg;
  1445.         write(outfh,(char *)&lreads,sizeof(struct _lmr));
  1446.         }        /* End of while loop */
  1447.     close(infh);
  1448.     close(outfh);
  1449.     unlink(old_name);
  1450.     return;
  1451. }
  1452.  
  1453.  
  1454. 
  1455.